import re

import logging
from django import http
from django.contrib.auth import login

from django.http import JsonResponse
from django.shortcuts import render, redirect

# Create your views here.

#https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=101518219&redirect_uri=http://www.meiduo.site:8000/oauth_callback&state=lalalala

# http://路由/?key=value&key1=value1
#我们的路由是以　？　为分割
# ? 前边为请求的路由
# ? 后边为请求的参数
from django.urls import reverse
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django_redis import get_redis_connection

from apps.oauth.models import OAuthQQUser
from apps.oauth.utils import generic_openid_token, check_openid_token
from apps.users.models import User
from utils.response_code import RETCODE
from meiduo_mall import settings
logger = logging.getLogger('django')
class OauthQQURLView(View):
    def get(self,request):
        # 我给你　　app_id redirect_uri
        # 你给我　一个跳转的url
        # 1.创建OAuthQQ实例
        # state与next 跳转到个人中心相同
        state = request.GET.get('next')
        qq = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            redirect_uri=settings.QQ_REDIRECT_URI,
            client_secret=settings.QQ_REDIRECT_URI,
            state=state,
        )
        # 2.调用实例方法
        login_url = qq.get_qq_url()
        # login_url = 'https://graph.qq.com/oauth2.0/show?which=Login&display=pc&response_type=code&client_id=101518219&redirect_uri=http://www.meiduo.site:8000/oauth_callback&state=test'

        return JsonResponse({'code':RETCODE.OK,'errmsg':'ok','login_url':login_url})


class OauthQQUserView(View):

    def  get(self,request):
        """
        1.获取code(是用户同意之后，qq服务器返回给我们的)

        2.通过code换取token(我们需要把code以及创建应用的serect一并给qq服务器，qq服务器会认证，
        认证没有问题会返回给我们token)
        3.根据ｔｏｋｅｎ换取ｏｐｅｎｉｄ（ｑｑ文档要求我们建立ｏｐｅｎｉｄ和当前应用ｕｓｅｒ要的一对一的关系）
        # 4.判断openid所对应的ｄuser信息是否存在
        # 5.如果不存在则进行绑定
        # 6.如果存在则进行登陆跳转

        """
        # 1.
        # 获取code(是用户同意之后，qq服务器返回给我们的)
        code = request.GET.get('code')
        if code is None:
            return http.HttpResponseBadRequest('参数有误')
        # 2.# 通过code换取token(我们需要把code以及创建应用的serect一并给qq服务器，qq服务器会认证，
        # 认证没有问题会返回给我们token)
            # 2.1创建OAuthQQ实例

        qq = OAuthQQ(
            client_id=settings.QQ_CLIENT_ID,
            redirect_uri=settings.QQ_REDIRECT_URI,
            client_secret=settings.QQ_CLIENT_SECRET,

        )

        # 通过code换取token
        token = qq.get_access_token(code)
        # 换取ｏｐｅｎｉｄ
        openid = qq.get_open_id(token)
        print(openid)
        # 4.判断openid所对应的ｄuser信息是否存在
        try:
            qquser = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 对一个已有的openid进行加密处理
            openid_token = generic_openid_token(openid)
            # 5.如果不存在则进行绑定
            return render(request,'oauth_callback.html',context={'openid':openid_token})


        else:
            # 没有异常的时候走
            # 6.如果存在则进行登陆跳转
            user = qquser.user
            # 6.1保持登陆状态
            login(request,user)
            # 6.2设置ｃｏｏｋｉｅ
            next = request.GET.get('state')
            if next:
                response = redirect(next)
            else:
                response = redirect(reverse('contents:index'))
            response.set_cookie('username',user.username,max_age=14*24*3600)
            # 6.３跳转


            return response

        # return render(request,'oauth_callback.html')

    def post(self,request):
        """
        需求：当用户点击保存的时候，需要让前端将openid_token,mobile,password,sms_code提交给后端

        后端：
        大体步骤：
        # １．接收数据
        # ２．验证数据
        # ３．绑定信息
        # 　　openid　　通过openid_token的解密获取
        #     user  需要根据　　手机号进行判断
        #     如果手机号注册，已经有user信息
        #     如果没有注册，我们就创建一个user用户
        # ４．登陆，状态保持
        # ５．cookie
        # 6．返回响应
        """
        # １．接收数据
        data = request.POST
        mobile=data.get('mobile')
        password = data.get('password')
        sms_code = data.get('sms_code')
        access_token = data.get('access_token')
        # ２．验证数据
        if not all([mobile,password,sms_code,access_token]):
            # from django import http
            return http.HttpResponseBadRequest('参数不全')

        # 验证手机号
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('手机号不符合规则')
        # 验证密码
        if not re.match(r'^[0-9A-Za-z]{8,20}$',password):
            return http.HttpResponseBadRequest('密码格式不正确')
        # 验证 用户提交的短信验证码和redis的短信验证码是否一致
        # 连接reids
        redis_conn = get_redis_connection('code')
        # 获取redis中的短信验证码
        sms_code_server = redis_conn.get('sms_%s' % mobile)
        # 判断redis中的短信验证码是否过期
        if not sms_code_server:
            return http.HttpResponseBadRequest('短信验证码已过期')
        # 比对
        if sms_code_server.decode() != sms_code:
            return http.HttpResponseBadRequest('短信验证码不一致')

        openid = check_openid_token(access_token)
        if openid is None:
            return http.HttpResponseBadRequest('openid错误')
        # ３．绑定信息
        # 　　openid　　通过openid_token的解密获取
        #     user  需要根据　　手机号进行判断
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            #     如果没有注册，我们就创建一个user用户
            user = User.objects.create_user(
                username=mobile,
                password=password,
                mobile=mobile,

            )
        else:
            #     如果手机号注册，已经有user信息
            # 再次验证密码是否正确
            if not user.check_password(password):
                return http.HttpResponseBadRequest('密码错误')
        # 操作数据库
        try:
            # 调用objects.create直接保存
            OAuthQQUser.objects.create(
                openid = openid,
                user = user,

            )
        except Exception as e:
            logger.error(e)
            return http.HttpResponseBadRequest('数据库错误')

        # ４．登陆，状态保持
        login(request,user)
        # ５．cookie
        response = redirect(reverse('contents:index'))
        response.set_cookie('username',user.username,max_age=14*24*3600)
        # 6．返回响应
        return response



####################itsdangerous加密####################
from itsdangerous import  TimedJSONWebSignatureSerializer as Serializer
from meiduo_mall import settings
# 1.创建实例对象
#secret_key.expires_in
#secret_key  秘钥
# pires_in   过期时间（秒）
s = Serializer(settings.SECRET_KEY,300)

# 2.组织数据
data = {'openid':'dfg'}
# 3.加密处理
token = s.dumps(data)
# b'eyJleHAiOjE1NTc5ODc2NjEsImFsZyI6IkhTNTEyIiwiaWF0IjoxNTU3OTg3MzYxfQ.eyJvcGVuaWQiOiJkZmcifQ.nLONbaOO735NqsbORb4pA4R3tiEwygJF-RuA1MWpweEr_Wxpp58E6O8bapuzMz7e_rOlNdtG4QcCvaU2iGlEKA'
token.decode()

####################itsdangerous解密####################

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from meiduo_mall import settings
#1.创建实例
s = Serializer(settings.SECRET_KEY,300)
#2.对数据进行解密
s.loads(token)

####################itsdangerous解密失败过期####################

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from meiduo_mall import settings
# 1.创建实例对象
#secret_key.expires_in
#secret_key  秘钥
# pires_in   过期时间（秒）
s = Serializer(settings.SECRET_KEY,1)

# 2.组织数 １
data = {'openid':'dfg'}
# 3.加密处理
token = s.dumps(data)
# b'eyJleHAiOjE1NTc5ODc2NjEsImFsZyI6IkhTNTEyIiwiaWF0IjoxNTU3OTg3MzYxfQ.eyJvcGVuaWQiOiJkZmcifQ.nLONbaOO735NqsbORb4pA4R3tiEwygJF-RuA1MWpweEr_Wxpp58E6O8bapuzMz7e_rOlNdtG4QcCvaU2iGlEKA'
token.decode()

"""
>>> s.loads(token)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/python/.virtualenvs/py3_meiduo_mall_40/lib/python3.5/site-packages/itsdangerous/jws.py", line 205, in loads
    date_signed=self.get_issue_date(header),
itsdangerous.exc.SignatureExpired: Signature expired
>>>

"""
####################篡改数据####################

from itsdangerous import  TimedJSONWebSignatureSerializer as Serializer
from meiduo_mall import settings
# 1.创建实例对象
#secret_key.expires_in
#secret_key  秘钥
# pires_in   过期时间（秒）
s = Serializer(settings.SECRET_KEY,300)

# 2.组织数据
data = {'openid':'dfg'}
# 3.加密处理
token = s.dumps(data)

"""
篡改数据后异常
raise BadSignature("Signature %r does not match" % sig, payload=value)
"""